//
//  SPHandEvaluator.m
//  ShandongPoker
//
//  Created by Developer on 2025-01-08.
//  Copyright © 2025 ShandongPoker. All rights reserved.
//

#import "SPHandEvaluator.h"

@implementation SPHandResult

- (instancetype)initWithHandRank:(SPHandRank)handRank 
                       bestCards:(NSArray<SPCard *> *)bestCards 
                     kickerCards:(NSArray<SPCard *> *)kickerCards {
    if (self = [super init]) {
        _handRank = handRank;
        _bestCards = bestCards;
        _kickerCards = kickerCards;
    }
    return self;
}

- (NSString *)handName {
    switch (self.handRank) {
        case SPHandRankHighCard:
            return @"高牌";
        case SPHandRankOnePair:
            return @"一对";
        case SPHandRankTwoPair:
            return @"两对";
        case SPHandRankThreeOfAKind:
            return @"三条";
        case SPHandRankStraight:
            return @"顺子";
        case SPHandRankFlush:
            return @"同花";
        case SPHandRankFullHouse:
            return @"葫芦";
        case SPHandRankFourOfAKind:
            return @"四条";
        case SPHandRankStraightFlush:
            return @"同花顺";
        case SPHandRankRoyalFlush:
            return @"皇家同花顺";
    }
}

- (NSInteger)score {
    // 基础分数：牌型 * 1000000
    NSInteger baseScore = self.handRank * 1000000;
    
    // 最佳牌分数
    NSInteger bestCardsScore = 0;
    for (NSInteger i = 0; i < self.bestCards.count; i++) {
        bestCardsScore += self.bestCards[i].value * (NSInteger)pow(100, self.bestCards.count - 1 - i);
    }
    
    // 踢脚牌分数
    NSInteger kickerScore = 0;
    for (NSInteger i = 0; i < self.kickerCards.count; i++) {
        kickerScore += self.kickerCards[i].value * (NSInteger)pow(100, self.kickerCards.count - 1 - i);
    }
    
    return baseScore + bestCardsScore + kickerScore;
}

@end

@implementation SPHandEvaluator

#pragma mark - Public Methods

+ (SPHandResult *)evaluateHandWithHoleCards:(NSArray<SPCard *> *)holeCards 
                             communityCards:(NSArray<SPCard *> *)communityCards {
    
    // 合并所有牌
    NSMutableArray<SPCard *> *allCards = [NSMutableArray arrayWithArray:holeCards];
    [allCards addObjectsFromArray:communityCards];
    
    // 获取所有可能的5张牌组合
    NSArray<NSArray<SPCard *> *> *combinations = [self allPossibleFiveCardCombinations:allCards];
    
    SPHandResult *bestResult = nil;
    
    // 评估每个组合
    for (NSArray<SPCard *> *combination in combinations) {
        SPHandResult *result = [self evaluateFiveCardHand:combination];
        
        if (!bestResult || [self compareHandResult:result withResult:bestResult] == NSOrderedDescending) {
            bestResult = result;
        }
    }
    
    return bestResult;
}

+ (NSComparisonResult)compareHandResult:(SPHandResult *)result1 
                            withResult:(SPHandResult *)result2 {
    
    if (result1.score > result2.score) {
        return NSOrderedDescending;
    } else if (result1.score < result2.score) {
        return NSOrderedAscending;
    } else {
        return NSOrderedSame;
    }
}

+ (BOOL)isFlush:(NSArray<SPCard *> *)cards {
    if (cards.count != 5) return NO;
    
    SPCardSuit firstSuit = cards[0].suit;
    for (SPCard *card in cards) {
        if (card.suit != firstSuit) {
            return NO;
        }
    }
    return YES;
}

+ (BOOL)isStraight:(NSArray<SPCard *> *)cards {
    if (cards.count != 5) return NO;
    
    // 按点数排序
    NSArray<SPCard *> *sortedCards = [cards sortedArrayUsingComparator:^NSComparisonResult(SPCard *card1, SPCard *card2) {
        return [card1 compare:card2];
    }];
    
    // 检查是否为连续的点数
    for (NSInteger i = 1; i < sortedCards.count; i++) {
        if (sortedCards[i].value != sortedCards[i-1].value + 1) {
            // 特殊处理A-2-3-4-5的顺子
            if (i == 4 && sortedCards[0].value == 2 && sortedCards[4].value == 14) {
                return YES;
            }
            return NO;
        }
    }
    return YES;
}

+ (BOOL)isStraightFlush:(NSArray<SPCard *> *)cards {
    return [self isFlush:cards] && [self isStraight:cards];
}

+ (BOOL)isRoyalFlush:(NSArray<SPCard *> *)cards {
    if (![self isStraightFlush:cards]) return NO;
    
    // 检查是否包含A和K
    BOOL hasAce = NO, hasKing = NO;
    for (SPCard *card in cards) {
        if (card.rank == SPCardRankAce) hasAce = YES;
        if (card.rank == SPCardRankKing) hasKing = YES;
    }
    
    return hasAce && hasKing;
}

+ (NSDictionary<NSNumber *, NSNumber *> *)rankFrequency:(NSArray<SPCard *> *)cards {
    NSMutableDictionary<NSNumber *, NSNumber *> *frequency = [[NSMutableDictionary alloc] init];
    
    for (SPCard *card in cards) {
        NSNumber *rank = @(card.rank);
        NSNumber *count = frequency[rank];
        frequency[rank] = @(count.integerValue + 1);
    }
    
    return [frequency copy];
}

+ (NSDictionary<NSNumber *, NSNumber *> *)suitFrequency:(NSArray<SPCard *> *)cards {
    NSMutableDictionary<NSNumber *, NSNumber *> *frequency = [[NSMutableDictionary alloc] init];
    
    for (SPCard *card in cards) {
        NSNumber *suit = @(card.suit);
        NSNumber *count = frequency[suit];
        frequency[suit] = @(count.integerValue + 1);
    }
    
    return [frequency copy];
}

+ (NSArray<NSArray<SPCard *> *> *)allPossibleFiveCardCombinations:(NSArray<SPCard *> *)cards {
    NSMutableArray<NSArray<SPCard *> *> *combinations = [[NSMutableArray alloc] init];
    
    if (cards.count < 5) {
        return combinations;
    }
    
    [self generateCombinations:cards 
                        start:0 
                         size:5 
                 combination:[[NSMutableArray alloc] init] 
                   result:combinations];
    
    return [combinations copy];
}

#pragma mark - Private Methods

+ (SPHandResult *)evaluateFiveCardHand:(NSArray<SPCard *> *)cards {
    // 按点数排序
    NSArray<SPCard *> *sortedCards = [cards sortedArrayUsingComparator:^NSComparisonResult(SPCard *card1, SPCard *card2) {
        return [card2 compare:card1]; // 降序排列
    }];
    
    // 获取频率信息
    NSDictionary<NSNumber *, NSNumber *> *rankFreq = [self rankFrequency:cards];
    
    // 判断牌型
    if ([self isRoyalFlush:cards]) {
        return [[SPHandResult alloc] initWithHandRank:SPHandRankRoyalFlush 
                                            bestCards:sortedCards 
                                          kickerCards:@[]];
    }
    
    if ([self isStraightFlush:cards]) {
        return [[SPHandResult alloc] initWithHandRank:SPHandRankStraightFlush 
                                            bestCards:sortedCards 
                                          kickerCards:@[]];
    }
    
    // 检查四条
    NSArray<NSNumber *> *fourOfAKind = [self findCardsWithFrequency:4 inRankFrequency:rankFreq];
    if (fourOfAKind.count > 0) {
        NSArray<SPCard *> *fourCards = [self cardsWithRank:fourOfAKind[0].integerValue fromCards:cards];
        NSArray<SPCard *> *kicker = [self cardsWithRank:[self findHighestRankExcluding:fourOfAKind[0].integerValue fromCards:cards] fromCards:cards];
        return [[SPHandResult alloc] initWithHandRank:SPHandRankFourOfAKind 
                                            bestCards:fourCards 
                                          kickerCards:kicker];
    }
    
    // 检查葫芦
    NSArray<NSNumber *> *threeOfAKind = [self findCardsWithFrequency:3 inRankFrequency:rankFreq];
    NSArray<NSNumber *> *pairs = [self findCardsWithFrequency:2 inRankFrequency:rankFreq];
    if (threeOfAKind.count > 0 && pairs.count > 0) {
        NSArray<SPCard *> *threeCards = [self cardsWithRank:threeOfAKind[0].integerValue fromCards:cards];
        NSArray<SPCard *> *pairCards = [self cardsWithRank:pairs[0].integerValue fromCards:cards];
        NSArray<SPCard *> *fullHouseCards = [threeCards arrayByAddingObjectsFromArray:pairCards];
        return [[SPHandResult alloc] initWithHandRank:SPHandRankFullHouse 
                                            bestCards:fullHouseCards 
                                          kickerCards:@[]];
    }
    
    // 检查同花
    if ([self isFlush:cards]) {
        return [[SPHandResult alloc] initWithHandRank:SPHandRankFlush 
                                            bestCards:sortedCards 
                                          kickerCards:@[]];
    }
    
    // 检查顺子
    if ([self isStraight:cards]) {
        return [[SPHandResult alloc] initWithHandRank:SPHandRankStraight 
                                            bestCards:sortedCards 
                                          kickerCards:@[]];
    }
    
    // 检查三条
    if (threeOfAKind.count > 0) {
        NSArray<SPCard *> *threeCards = [self cardsWithRank:threeOfAKind[0].integerValue fromCards:cards];
        NSArray<SPCard *> *kickers = [self findKickersExcludingRank:threeOfAKind[0].integerValue fromCards:cards count:2];
        return [[SPHandResult alloc] initWithHandRank:SPHandRankThreeOfAKind 
                                            bestCards:threeCards 
                                          kickerCards:kickers];
    }
    
    // 检查两对
    if (pairs.count >= 2) {
        NSArray<SPCard *> *pair1Cards = [self cardsWithRank:pairs[0].integerValue fromCards:cards];
        NSArray<SPCard *> *pair2Cards = [self cardsWithRank:pairs[1].integerValue fromCards:cards];
        NSArray<SPCard *> *twoPairCards = [pair1Cards arrayByAddingObjectsFromArray:pair2Cards];
        NSArray<SPCard *> *kicker = [self cardsWithRank:[self findHighestRankExcluding:pairs[0].integerValue excludingRank:pairs[1].integerValue fromCards:cards] fromCards:cards];
        return [[SPHandResult alloc] initWithHandRank:SPHandRankTwoPair 
                                            bestCards:twoPairCards 
                                          kickerCards:kicker];
    }
    
    // 检查一对
    if (pairs.count > 0) {
        NSArray<SPCard *> *pairCards = [self cardsWithRank:pairs[0].integerValue fromCards:cards];
        NSArray<SPCard *> *kickers = [self findKickersExcludingRank:pairs[0].integerValue fromCards:cards count:3];
        return [[SPHandResult alloc] initWithHandRank:SPHandRankOnePair 
                                            bestCards:pairCards 
                                          kickerCards:kickers];
    }
    
    // 高牌
    return [[SPHandResult alloc] initWithHandRank:SPHandRankHighCard 
                                        bestCards:sortedCards 
                                      kickerCards:@[]];
}

+ (void)generateCombinations:(NSArray<SPCard *> *)cards 
                       start:(NSInteger)start 
                        size:(NSInteger)size 
                combination:(NSMutableArray<SPCard *> *)combination 
                      result:(NSMutableArray<NSArray<SPCard *> *> *)result {
    
    if (combination.count == size) {
        [result addObject:[combination copy]];
        return;
    }
    
    for (NSInteger i = start; i < cards.count; i++) {
        [combination addObject:cards[i]];
        [self generateCombinations:cards 
                            start:i + 1 
                             size:size 
                     combination:combination 
                           result:result];
        [combination removeLastObject];
    }
}

+ (NSArray<NSNumber *> *)findCardsWithFrequency:(NSInteger)frequency 
                                inRankFrequency:(NSDictionary<NSNumber *, NSNumber *> *)rankFreq {
    NSMutableArray<NSNumber *> *result = [[NSMutableArray alloc] init];
    
    for (NSNumber *rank in rankFreq.allKeys) {
        if (rankFreq[rank].integerValue == frequency) {
            [result addObject:rank];
        }
    }
    
    // 按点数降序排列
    return [result sortedArrayUsingComparator:^NSComparisonResult(NSNumber *rank1, NSNumber *rank2) {
        return [rank2 compare:rank1];
    }];
}

+ (NSArray<SPCard *> *)cardsWithRank:(SPCardRank)rank fromCards:(NSArray<SPCard *> *)cards {
    NSMutableArray<SPCard *> *result = [[NSMutableArray alloc] init];
    
    for (SPCard *card in cards) {
        if (card.rank == rank) {
            [result addObject:card];
        }
    }
    
    return [result copy];
}

+ (SPCardRank)findHighestRankExcluding:(SPCardRank)excludeRank fromCards:(NSArray<SPCard *> *)cards {
    SPCardRank highestRank = 0;
    
    for (SPCard *card in cards) {
        if (card.rank != excludeRank && card.rank > highestRank) {
            highestRank = card.rank;
        }
    }
    
    return highestRank;
}

+ (SPCardRank)findHighestRankExcluding:(SPCardRank)excludeRank1 
                          excludingRank:(SPCardRank)excludeRank2 
                              fromCards:(NSArray<SPCard *> *)cards {
    SPCardRank highestRank = 0;
    
    for (SPCard *card in cards) {
        if (card.rank != excludeRank1 && card.rank != excludeRank2 && card.rank > highestRank) {
            highestRank = card.rank;
        }
    }
    
    return highestRank;
}

+ (NSArray<SPCard *> *)findKickersExcludingRank:(SPCardRank)excludeRank 
                                      fromCards:(NSArray<SPCard *> *)cards 
                                          count:(NSInteger)count {
    NSMutableArray<SPCard *> *kickers = [[NSMutableArray alloc] init];
    
    for (SPCard *card in cards) {
        if (card.rank != excludeRank && kickers.count < count) {
            [kickers addObject:card];
        }
    }
    
    // 按点数降序排列
    return [kickers sortedArrayUsingComparator:^NSComparisonResult(SPCard *card1, SPCard *card2) {
        return [card2 compare:card1];
    }];
}

@end 